﻿using Furion.DataEncryption;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using BaseNet.Application.System.User.Dto;
using BaseNet.Core.Consts;
using BaseNet.Core.Dtos;
using BaseNet.Core.Utils;
using BaseNet.Entity.System;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

namespace BaseNet.Application.System.User
{
    [ApiDescriptionSettings(Module = ModuleConsts.System)]
    [SecurityDefine(SecurityConsts.System_User)]
    public class UserService : IDynamicApiController
    {
        private readonly SqlSugarClient _db;
        public UserService(ISqlSugarRepository sqlSugarRepository)
        {
            _db = sqlSugarRepository.Context;
        }

        /// <summary>
        /// 添加系统用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task Add(SysUserSaveInput input)
        {
            using (var mutex = new Mutex(true, "/api/system/user/add/"))
            {
                try
                {
                    if (!mutex.WaitOne(0, true))//若存在接口堵塞，则直接退出
                        throw Oops.Oh("当前接口存在正在进行的访问");

                    //判断数据有效性
                    if (_db.Queryable<SysUserEntity>().Where(o => o.Account == input.Account.Trim()).Any())
                        throw Oops.Oh("账号不可重复");

                    //1.添加系统用户
                    var entity = input.Adapt<SysUserEntity>();
                    entity.Password = MD5Encryption.Encrypt(input.Password.Trim());

                    //2.添加用户角色关联表数据
                    var roleIds = input.RoleIds.Split(",").Where(o => !string.IsNullOrWhiteSpace(o));
                    var sysUserRoleList = roleIds.Select(o => new SysUserRoleEntity
                    {
                        RoleId = o,
                        UserId = entity.Id
                    }).ToList();

                    await _db.UseTranAsync(async () =>
                    {
                        await _db.ExtInsertableAsync(entity);
                        await _db.ExtInsertableAsync(sysUserRoleList);
                    }, o => throw Oops.Oh(o.Message));
                }
                finally
                {
                    try
                    {
                        mutex.ReleaseMutex();
                    }
                    catch (Exception) { }
                    mutex.Close();
                    mutex.Dispose();
                }
            }
        }

        /// <summary>
        /// 编辑系统用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task Edit(SysUserSaveInput input)
        {
            using (var mutex = new Mutex(true, "/api/system/user/add/"))
            {
                try
                {
                    if (!mutex.WaitOne(0, true))//若存在接口堵塞，则直接退出
                        throw Oops.Oh("当前接口存在正在进行的访问");

                    var roleIds = input.RoleIds.Split(",").Where(o => !string.IsNullOrWhiteSpace(o));

                    //1.修改系统用户
                    var entity = await _db.Queryable<SysUserEntity>()
                        .Where(o => o.Id == input.Id)
                        .FirstAsync();
                    if (entity == null)
                        throw Oops.Oh("当前用户不存在");

                    if (await _db.Queryable<SysUserEntity>().Where(o => o.Account == input.Account.Trim() && o.Id != input.Id).AnyAsync())
                        throw Oops.Oh("账号不可重复");

                    entity.Password = !string.IsNullOrWhiteSpace(input.Password) ? MD5Encryption.Encrypt(input.Password.Trim()) : entity.Password;
                    entity.IsActive = input.IsActive;

                    //2.移除原先的用户角色关联表
                    var oldSysUserRoleList = await _db.Queryable<SysUserRoleEntity>()
                        .Where(o => o.UserId == entity.Id)
                        .ToListAsync();

                    //3.添加新的用户角色关联表数据
                    var sysUserRoleList = roleIds.Select(o => new SysUserRoleEntity
                    {
                        RoleId = o,
                        UserId = entity.Id
                    }).ToList();

                    await _db.UseTranAsync(async () =>
                    {
                        await _db.ExtUpdateableAsync(entity);
                        await _db.ExtDeleteableAsync(oldSysUserRoleList);
                        await _db.ExtInsertableAsync(sysUserRoleList);
                    }, o => throw Oops.Oh(o.Message));
                }
                finally
                {
                    try
                    {
                        mutex.ReleaseMutex();
                    }
                    catch (Exception) { }
                    mutex.Close();
                    mutex.Dispose();
                }
            }
        }

        /// <summary>
        /// 删除系统用户
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task Del(PrivateEntityBase input)
        {
            using (var mutex = new Mutex(true, "/api/system/user/del/" + input.Id))
            {
                try
                {
                    if (!mutex.WaitOne(0, true))//若存在接口堵塞，则直接退出
                        throw Oops.Oh("当前接口存在正在进行的访问");

                    //1.删除系统用户
                    var entity = await _db.Queryable<SysUserEntity>()
                        .Where(o => o.Id == input.Id)
                        .FirstAsync();
                    if (entity == null)
                        throw Oops.Oh("当前用户不存在");

                    //2.移除原先的用户角色关联表
                    var oldSysUserRoleList = await _db.Queryable<SysUserRoleEntity>()
                        .Where(o => o.UserId == entity.Id)
                        .ToListAsync();

                    await _db.UseTranAsync(async () =>
                    {
                        await _db.ExtDeleteableAsync(entity);
                        await _db.ExtDeleteableAsync(oldSysUserRoleList);
                    }, o => throw Oops.Oh(o.Message));
                }
                finally
                {
                    try
                    {
                        mutex.ReleaseMutex();
                    }
                    catch (Exception) { }
                    mutex.Close();
                    mutex.Dispose();
                }
            }
        }

        /// <summary>
        /// 设置用户有效性
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task SetActive(PrivateEntityBase input)
        {
            using (var mutex = new Mutex(true, "/api/system/user/del/" + input.Id))
            {
                try
                {
                    if (!mutex.WaitOne(0, true))//若存在接口堵塞，则直接退出
                        throw Oops.Oh("当前接口存在正在进行的访问");

                    var entity = await _db.Queryable<SysUserEntity>()
                        .Where(o => o.Id == input.Id)
                        .FirstAsync();
                    if (entity == null)
                        throw Oops.Oh("当前用户不存在");

                    entity.IsActive = !entity.IsActive;

                    await _db.ExtUpdateableAsync(entity);
                }
                finally
                {
                    try
                    {
                        mutex.ReleaseMutex();
                    }
                    catch (Exception) { }
                    mutex.Close();
                    mutex.Dispose();
                }
            }
        }

        /// <summary>
        /// 获取用户详情
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<SysUserDto> GetInfo(PrivateEntityBase input)
        {
            var dto = await _db.Queryable<SysUserEntity>()
                .Where(o => o.Id == input.Id)
                .Select<SysUserDto>()
                .FirstAsync();
            if (dto == null)
                throw Oops.Oh("当前用户不存在"); 

            var roleIds = await _db.Queryable<SysUserRoleEntity>()
                .Where(o => o.UserId == dto.Id)
                .Select(o => o.RoleId)
                .Distinct()
                .ToListAsync();

            dto.RoleIds = roleIds;
            return dto;
        }

        /// <summary>
        /// 获取系统用户分页列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<SqlSugarPagedList<SysUserDto>> GetPagedList(SysUserPagedInput input)
        {
            var roleIds = input.RoleIds.Split(",").Where(o => !string.IsNullOrWhiteSpace(o));

            var list = await _db.Queryable<SysUserEntity>()
                .WhereIF(!string.IsNullOrWhiteSpace(input.KeyWord), o => o.Account.Contains(input.KeyWord))
                .WhereIF(input.IsActive.HasValue, o => o.IsActive == input.IsActive)
                .WhereIF(roleIds.Count() > 0, o => SqlFunc.Subqueryable<SysUserRoleEntity>().Where(x => x.UserId == o.Id).Where(x => input.RoleIds.Contains(x.RoleId)).Any())
                .OrderByIF(!string.IsNullOrWhiteSpace(input.OrderByField), input.OrderByField)
                .Select<SysUserDto>()
                .ToPagedListAsync(input.PageIndex, input.PageSize);

            var userIds = list.Items.Select(o => o.Id).ToList();

            var sysUserRoleList = await _db.Queryable<SysUserRoleEntity>()
                .Where(o => userIds.Contains(o.UserId))
                .ToListAsync();
            var sysUserRoleIds = sysUserRoleList.Select(o => o.RoleId).Distinct().ToList();
            var sysRoleList = await _db.Queryable<SysRoleEntity>()
                .Where(o => o.IsActive == true)
                .Where(o => sysUserRoleIds.Contains(o.Id))
                .ToListAsync();

            foreach (var item in list.Items)
            {
                var self_sysUserRoleList = sysUserRoleList.FindAll(o => o.UserId == item.Id);//当前用户的角色关联列表
                var self_sysRoleIds = self_sysUserRoleList.Select(o => o.RoleId).Distinct().ToList();
                var self_sysRoleList = sysRoleList.FindAll(o => self_sysRoleIds.Contains(o.Id));//当前用户的角色列表
                var self_roleList = self_sysRoleList.Select(o => o.Name).ToList();
                item.RoleIds = self_sysRoleIds;
                item.RoleNames = string.Join(",", self_roleList);
            }

            return list;
        }

    }
}
